package me.helllp.bootman.back.aop;

import java.lang.reflect.Method;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;

import com.alibaba.fastjson.JSON;

import me.helllp.bootman.common.utils.ResultUtil;


/** 
 * 拦截器：记录用户操作日志 
 */  
@Aspect
@Component  
public class ControllerInterceptor {  
    private static final Logger logger = LoggerFactory.getLogger(ControllerInterceptor.class);  
      
    @Value("${spring.profiles.active}")  
    private String env;  
     
    /** 
     * 定义拦截规则：拦截logic包下面的所有类中 
     */
    @Pointcut("execution(* com.icfans.paltform.logic..*.*(..))")  
    public void controllerMethodPointcut(){}  
    
    /**
     * 定义拦截规则：使用了HTTP注解的方法
     */
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping) "
    		+ "|| @annotation(org.springframework.web.bind.annotation.PostMapping) "
    		+ "|| @annotation(org.springframework.web.bind.annotation.GetMapping) "
    		+ "|| @annotation(org.springframework.web.bind.annotation.PutMapping) "
    		+ "|| @annotation(org.springframework.web.bind.annotation.DeleteMapping)")
    public void controllerAnnotationPointcut(){}
    
//    private String a = org.springframework.http.HttpMethod.DELETE.name();
    
    /** 
     * 拦截器具体实现 
     * @param pjp 
     * @return 
     */  
//    @Around("controllerMethodPointcut() && controllerAnnotationPointcut()")
    @Around("controllerAnnotationPointcut()")
    public Object Interceptor(ProceedingJoinPoint pjp){  
          
        MethodSignature signature = (MethodSignature) pjp.getSignature();  
        
        Method method = signature.getMethod(); //获取被拦截的方法
        String className = method.getClass().getName();
        String methodName = method.getName(); //获取被拦截的方法名  
          
        logger.info(className + "的" + methodName + "执行了");

        paramParser(pjp.getArgs());
        
        Object result = null;  
 
        long beginTime = System.currentTimeMillis();
        
        try {  
            if(result == null){  
                // 一切正常的情况下，继续执行被拦截的方法  
                result = pjp.proceed();  
            }  
        }catch (Exception e){
        	result = ResultUtil.genSuccessResult("粗我的信息");
        } catch (Throwable e) {
			e.printStackTrace();
		} 
          
        long costMs = System.currentTimeMillis() - beginTime;  
        logger.info("{}请求结束，耗时：{}ms，返回值：{}", methodName, costMs, result);
        
        
        return result;  
    }  
     
    private void paramParser(Object[] args) {
        //	保存所有请求参数，用于输出到日志中
        Set<Object> allParams = new LinkedHashSet<>();
        
        for(Object arg : args){  
            if (arg instanceof Map<?, ?>) {  
                //提取方法中的MAP参数，用于记录进日志中  
                @SuppressWarnings("unchecked")  
                Map<String, Object> map = (Map<String, Object>) arg;  
  
                allParams.add(map);  
            }else if(arg instanceof HttpServletRequest){  
                HttpServletRequest request = (HttpServletRequest) arg;  
                  
				// 获取query string 或 posted form data参数
				Map<String, String[]> paramMap = request.getParameterMap();

				if (paramMap != null && paramMap.size() > 0) {

					allParams.add(paramMap);
				} 
            }else if(arg instanceof HttpServletResponse){  
                //	do nothing...  
            }else if(arg instanceof BindingResult){
            	//	do noting...
            }else{  
                allParams.add(arg);  
            }  
        }  
          
        logger.info("请求参数：{}",JSON.toJSONString(allParams));
    }    
}  